This document describes a common interface for sending HTTP requests and receiving HTTP responses.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
The goal of this PSR is to allow developers to create libraries decoupled from HTTP client implementations. This will make libraries more reusable as it reduces the number of dependencies and lowers the likelihood of version conflicts.
A second goal is that HTTP clients can be replaced as per the Liskov substitution principle. This means that all clients MUST behave in the same way when sending a request.
A Client is an object implementing ClientInterface
.
A Client MAY:
If a Client chooses to alter either the HTTP request or HTTP response, it MUST ensure that the
object remains internally consistent. For example, if a Client chooses to decompress the message
body then it MUST also remove the Content-Encoding
header and adjust the Content-Length
header.
Note that as a result, since PSR-7 objects are immutable,
the Calling Library MUST NOT assume that the object passed to ClientInterface::sendRequest()
will be the same PHP object
that is actually sent. For example, the Request object that is returned by an exception MAY be a different object than
the one passed to sendRequest()
, so comparison by reference (===) is not possible.
A Client MUST:
A Client MUST NOT treat a well-formed HTTP request or HTTP response as an error condition. For example, response status codes in the 400 and 500 range MUST NOT cause an exception and MUST be returned to the Calling Library as normal.
A Client MUST throw an instance of Psr\Http\Client\ClientExceptionInterface
if and only if it is unable to send
the HTTP request at all or if the HTTP response could not be parsed into a PSR-7 response object.
If a request cannot be sent because the request message is not a well-formed HTTP request or is missing some critical
piece of information (such as a Host or Method), the Client MUST throw an instance of Psr\Http\Client\RequestExceptionInterface
.
If the request cannot be sent due to a network failure of any kind, including a timeout, the Client MUST throw an
instance of Psr\Http\Client\NetworkExceptionInterface
.
Clients MAY throw more specific exceptions than those defined here (a TimeOutException
or HostNotFoundException
for
example), provided they implement the appropriate interface defined above.
namespace Psr\Http\Client;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
interface ClientInterface
{
/**
* Sends a PSR-7 request and returns a PSR-7 response.
*
* @param RequestInterface $request
*
* @return ResponseInterface
*
* @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request.
*/
public function sendRequest(RequestInterface $request): ResponseInterface;
}
namespace Psr\Http\Client;
/**
* Every HTTP client related exception MUST implement this interface.
*/
interface ClientExceptionInterface extends \Throwable
{
}
namespace Psr\Http\Client;
use Psr\Http\Message\RequestInterface;
/**
* Exception for when a request failed.
*
* Examples:
* - Request is invalid (e.g. method is missing)
* - Runtime request errors (e.g. the body stream is not seekable)
*/
interface RequestExceptionInterface extends ClientExceptionInterface
{
/**
* Returns the request.
*
* The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
*
* @return RequestInterface
*/
public function getRequest(): RequestInterface;
}
namespace Psr\Http\Client;
use Psr\Http\Message\RequestInterface;
/**
* Thrown when the request cannot be completed because of network issues.
*
* There is no response object as this exception is thrown when no response has been received.
*
* Example: the target host name can not be resolved or the connection failed.
*/
interface NetworkExceptionInterface extends ClientExceptionInterface
{
/**
* Returns the request.
*
* The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
*
* @return RequestInterface
*/
public function getRequest(): RequestInterface;
}